#include <cstdint>
#include <iostream>
#include <vector>
#include <algorithm>

using ll = int64_t;
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    ll n, m, k;
    cin >> n >> m >> k;
    vector<string> v(n);
    for (ll i = 0; i < n; i++) {
        cin >> v[i];
    }

    vector<ll> dp(k + 1, 1e9);
    dp[0] = 0;

    for (ll i = 0; i < n; i++) {
        vector<ll> a;
        for (ll j = 0; j < m; j++) {
            if (v[i][j] == '1') {
                a.push_back(j);
            }
        }
        ll p = a.size();
        vector<ll> f(p + 1, 0);

        if (p == 0) {
            vector<ll> ndp = dp;
            dp = move(ndp);
            continue;
        }

        f[p] = 0;
        for (ll t = 0; t < p; t++) {
            ll b = p - 1 - t;
            ll mval = 1e9;
            for (ll x = 0; x <= t; x++) {
                ll cost = a[b + x] - a[x] + 1;
                if (cost < mval) {
                    mval = cost;
                }
            }
            f[t] = mval;
        }

        vector<ll> ndp(k + 1, 1e9);
        for (ll j = 0; j <= k; j++) {
            for (ll t = 0; t <= min(p, j); t++) {
                if (dp[j - t] != 1e9) {
                    if (dp[j - t] + f[t] < ndp[j]) {
                        ndp[j] = dp[j - t] + f[t];
                    }
                }
            }
        }
        dp = move(ndp);
    }

    ll ans = *min_element(dp.begin(), dp.end());
    cout << ans << endl;

    return 0;
}
/*
输入处理：

读取矩阵的行数 n、列数 m 和最多可删除的1的数量 k。

读取矩阵的每一行字符串。

动态规划初始化：

初始化 dp 数组，大小为 k+1，dp[0] = 0 表示初始状态（无删除）的代价为0，其余初始化为一个大数（表示不可达）。

处理每一行：

收集每行中1的位置索引到数组 a。

如果该行没有1，则直接跳过（代价为0）。

否则，计算该行删除 t 个1后的最小代价 f(t)：

f[p] = 0 表示删除所有1后代价为0。

对于 0 ≤ t < p，计算删除左侧 x 个和右侧 y 个1（x + y = t）后，剩余1的第一个和最后一个位置形成的区间长度，取最小值作为 f(t)。

更新动态规划状态：

对于当前行，枚举总删除数 j（0 到 k），枚举当前行删除数 t（0 到 min(p, j)）。

更新 ndp[j] 为 dp[j - t] + f[t] 的最小值。

输出结果：

最终答案为 dp[0..k] 中的最小值，即所有行在删除不超过 k 个1的情况下的最小总代价。

*/